require "prefabutil"
require "modutil"
require "recipe"

--------------------

local cooking = require("cooking")

--------------------

local assets=
{
    Asset("ANIM", "anim/backpack.zip"),
    Asset("ANIM", "anim/swap_betterbag.zip"),
    Asset("ATLAS", "images/inventoryimages/betterbag.xml"),

    Asset("ATLAS", "images/betterbagbg_7x2.xml"),
    Asset("ATLAS", "images/betterbagbg_8x2.xml"),
    Asset("ATLAS", "images/betterbagbg_9x2.xml"),
    Asset("ATLAS", "images/betterbagbg_10x2.xml"),
    Asset("ATLAS", "images/betterbagbg_10x3.xml"),
    Asset("ATLAS", "images/betterbagbg_10x5.xml"),
    Asset("ATLAS", "images/betterbagbg_8x8.xml"),
}

local function giveitems(inst, eventdata)
    if eventdata.owner.components.inventory and eventdata.recipe then
        for ik, iv in pairs(eventdata.recipe.ingredients) do
            if not eventdata.owner.components.inventory:Has(iv.type, iv.amount) then
                for i = 1, iv.amount do
                    local item = SpawnPrefab(iv.type)
                    eventdata.owner.components.inventory:GiveItem(item)
                end
            end
        end
    end
end

-------------------- 体温调控 --------------------

-- 动态维持体温
local function maintain_temperature(inst, equiper)
    if not inst.temp_task and TUNING.BETTERBAG_TEMPERATURE == 1 and equiper.components.temperature then
        inst.temp_task = inst:DoPeriodicTask(1, function()
            if equiper:IsValid() and equiper.components.temperature then
                local target_temp = 37
                -- 应用温度调整
                equiper.components.temperature:SetTemperature(target_temp)
            end
        end)
    end
end

local function stop_maintaining_temperature(inst)
    if inst.temp_task then
        inst.temp_task:Cancel()
        inst.temp_task = nil
    end
end

-------------------- 绝缘效果 --------------------

local function apply_insulation(inst, equiper)
    if equiper.components and equiper.components.playerlightningtarget then
        inst.old_lightning_chance = equiper.components.playerlightningtarget:GetHitChance()
        equiper.components.playerlightningtarget:SetHitChance(0)
    end
end

local function remove_insulation(inst, equiper)
    if equiper.components and equiper.components.playerlightningtarget and inst.old_lightning_chance then
        equiper.components.playerlightningtarget:SetHitChance(inst.old_lightning_chance)
    end
end

-------------------- 恢复效果 --------------------

local function apply_regeneration(inst, equiper)
    if not TUNING.BETTERBAG_REGENERATION then return end
    
    -- 初始化计时器
    inst.health_regen_timer = 0
    inst.hunger_regen_timer = 0
    inst.sanity_regen_timer = 0
    
    -- 启动恢复任务
    if inst.regeneration_task == nil then
        inst.regeneration_task = inst:DoPeriodicTask(0.1, function()
            if not equiper:IsValid() or equiper.components.health == nil then
                return
            end
            
            -- 生命恢复
            if TUNING.BETTERBAG_HEALTH_REGEN > 0 then
                inst.health_regen_timer = inst.health_regen_timer + 0.1
                if inst.health_regen_timer >= TUNING.BETTERBAG_HEALTH_REGEN_INTERVAL then
                    inst.health_regen_timer = 0
                    equiper.components.health:DoDelta(TUNING.BETTERBAG_HEALTH_REGEN, false, "betterbag")
                end
            end
            
            -- 饥饿恢复
            if TUNING.BETTERBAG_HUNGER_REGEN > 0 and equiper.components.hunger then
                inst.hunger_regen_timer = inst.hunger_regen_timer + 0.1
                if inst.hunger_regen_timer >= TUNING.BETTERBAG_HUNGER_REGEN_INTERVAL then
                    inst.hunger_regen_timer = 0
                    equiper.components.hunger:DoDelta(TUNING.BETTERBAG_HUNGER_REGEN)
                end
            end
            
            -- 理智恢复
            if TUNING.BETTERBAG_SANITY_REGEN > 0 and equiper.components.sanity then
                inst.sanity_regen_timer = inst.sanity_regen_timer + 0.1
                if inst.sanity_regen_timer >= TUNING.BETTERBAG_SANITY_REGEN_INTERVAL then
                    inst.sanity_regen_timer = 0
                    equiper.components.sanity:DoDelta(TUNING.BETTERBAG_SANITY_REGEN)
                end
            end
        end)
    end
end

-- 移除恢复效果
local function remove_regeneration(inst)
    if inst.regeneration_task then
        inst.regeneration_task:Cancel()
        inst.regeneration_task = nil
    end
end

-------------------- 装备/卸下函数 --------------------

local function onequip(inst, equiper)

    print("准备超级背包")

    -- light
    if TUNING.BETTERBAG_LIGHT and TUNING.BETTERBAG_LIGHT > 0 then
        inst.Light:Enable(true)
    end

    -- original
    local skin_build = inst:GetSkinBuild()
    if skin_build ~= nil then
        equiper:PushEvent("equipskinneditem", inst:GetSkinName())
        equiper.AnimState:OverrideItemSkinSymbol("betterbag", skin_build, "betterbag", inst.GUID, "swap_backpack" )
        equiper.AnimState:OverrideItemSkinSymbol("swap_body", skin_build, "swap_body", inst.GUID, "swap_backpack" )
    else
        equiper.AnimState:OverrideSymbol("swap_body", "swap_betterbag", "backpack")
        equiper.AnimState:OverrideSymbol("swap_body", "swap_betterbag", "swap_body")
    end
    if inst.components.container ~= nil then
        inst.components.container:Open(equiper)
    end

    -- 体温调控
    maintain_temperature(inst, equiper)
    -- 添加绝缘效果
    apply_insulation(inst, equiper)
    -- 添加恢复效果
    apply_regeneration(inst, equiper)
end

local function onunequip(inst, equiper)

    print("卸下超级背包")

    -- light
    if TUNING.BETTERBAG_LIGHT then
        inst.Light:Enable(false)
    end

    -- original
    local skin_build = inst:GetSkinBuild()
    if skin_build ~= nil then
        equiper:PushEvent("unequipskinneditem", inst:GetSkinName())
    end
    equiper.AnimState:ClearOverrideSymbol("swap_body")
    equiper.AnimState:ClearOverrideSymbol("backpack")
    if inst.components.container ~= nil then
        inst.components.container:Close(equiper)
    end

    -- 体温调控
    stop_maintaining_temperature(inst)
    -- 移除绝缘效果
    remove_insulation(inst, equiper)
    -- 移除恢复效果
    remove_regeneration(inst)
end

--------------------------------------------------------------------------

local function fn()
    local inst = CreateEntity()
    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddSoundEmitter()
    inst.entity:AddMiniMapEntity()
    inst.entity:AddNetwork()

    MakeInventoryPhysics(inst)
    inst.MiniMapEntity:SetIcon("betterbag.tex")

    if TUNING.BETTERBAG_LIGHT and TUNING.BETTERBAG_LIGHT > 0 then
        inst.entity:AddLight()
        inst.Light:Enable(false)
        local radius_tab = { [1]=1.5, [2]=2.0, [3]=3.0, [4]=4.0, [5]=5.0, [6]=8.0 }
        inst.Light:SetRadius(radius_tab[TUNING.BETTERBAG_LIGHT] or 1.5)
        inst.Light:SetFalloff(0.7)
        inst.Light:SetIntensity(0.6)
        inst.Light:SetColour(1,1,1)
    end

    inst:AddTag("fridge")
    inst:AddTag("nocool")
    inst:AddTag("umbrella")
    inst:AddTag("betterbag")

    inst.AnimState:SetBank("backpack1")
    inst.AnimState:SetBuild("swap_betterbag")
    inst.AnimState:PlayAnimation("anim")
    inst.foleysound = "dontstarve/movement/foley/krampuspack"

    inst.entity:SetPristine()
    if not TheWorld.ismastersim then return inst end

    -------------------- 容器 --------------------
    inst:AddComponent("container")
    inst.components.container:WidgetSetup("betterbag")
    inst.components.container.onopenfn  = function(inst) inst.SoundEmitter:PlaySound("dontstarve/wilson/chest_open") end
    inst.components.container.onclosefn = function(inst) inst.SoundEmitter:PlaySound("dontstarve/wilson/chest_close") end

    -------------------- 保鲜 --------------------
    local FreshRate = TUNING.BETTERBAG_FRESH
    inst:AddComponent("preserver")
    inst.components.preserver:SetPerishRateMultiplier(FreshRate)

    inst:AddComponent("inspectable")
    inst:AddComponent("inventoryitem")
    inst.components.inventoryitem.atlasname = "images/inventoryimages/betterbag.xml"
    inst.components.inventoryitem.imagename = "betterbag"
    inst.components.inventoryitem.cangoincontainer = true

    inst:AddComponent("equippable")
    inst.components.equippable.equipslot = EQUIPSLOTS.BACK or EQUIPSLOTS.BODY
    inst.components.equippable.insulated = true
    inst.components.equippable:SetOnEquip(onequip)
    inst.components.equippable:SetOnUnequip(onunequip)
    inst.components.equippable.walkspeedmult = TUNING.BETTERBAG_WALKSPEED

    inst.regeneration_task = nil
    inst.health_regen_timer = 0
    inst.hunger_regen_timer = 0
    inst.sanity_regen_timer = 0
    inst.old_lightning_chance = nil
    inst.temp_task = nil

    return inst
end

if TUNING.BETTERBAG_LANG == 0 then

    STRINGS.NAMES.BETTERBAG                                     = "超级背包"
    STRINGS.RECIPE_DESC.BETTERBAG                               = "一个好大好大的背包！"

else

    STRINGS.NAMES.BETTERBAG                                     = "Super Bag"
    STRINGS.RECIPE_DESC.BETTERBAG                               = "A super big bag！"

end

return Prefab( "common/inventory/betterbag", fn, assets)